package com.example.nio.security.config;

import com.example.nio.security.custom.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer;
import org.springframework.security.web.authentication.AnonymousAuthenticationFilter;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

@EnableGlobalMethodSecurity(prePostEnabled = true) // 开启方法级安全验证
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    private AdminAuthenticationSuccessHandler adminAuthenticationSuccessHandler;
@Autowired
private UnauthenticationFailureHandler unauthenticationFailureHandler;
    @Autowired
    private UnauthorizedEntryPointImpl entryPoint;
    @Autowired
    private MyAnonymousAuthenticationFilter myAnonymousAuthenticationFilter;

    @Override
    protected void configure(HttpSecurity http) throws Exception{
        ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry registry = http.antMatcher("/**").authorizeRequests();
        // 禁用CSRF 开启跨域
        http.csrf().disable().cors();
        // 登录处理 - 前后端一体的情况下
//        registry.and().formLogin().loginPage("/login").defaultSuccessUrl("/").permitAll()
//                // 自定义登陆用户名和密码属性名，默认为 username和password
//                .usernameParameter("username").passwordParameter("password")
//                // 异常处理
//                .failureUrl("/login/error").permitAll()
//                // 退出登录
//                .and().logout().permitAll();
//        registry.and().formLogin().loginPage("/loginUrl").successHandler(adminAuthenticationSuccessHandler)
        registry.and().formLogin().successHandler(adminAuthenticationSuccessHandler)
                .failureHandler(new AdminAuthenticationFailureHandler());
        // 添加认证失败处理器
        http.exceptionHandling().accessDeniedHandler(unauthenticationFailureHandler).authenticationEntryPoint(entryPoint);
        // 标识只能在 服务器本地ip[127.0.0.1或localhost] 访问`/home`接口，其他ip地址无法访问
        registry.antMatchers("/home").hasIpAddress("127.0.0.1");
        // 允许匿名的url - 可理解为放行接口 - 多个接口使用,分割
        registry.antMatchers("/auth/logout","/imagUpload","/showPicture/*","/OftenReply/**","/agent/**").permitAll();
        // OPTIONS(选项)：查找适用于一个特定网址资源的通讯选择。 在不需执行具体的涉及数据传输的动作情况下， 允许客户端来确定与资源相关的选项以及 / 或者要求， 或是一个服务器的性能
        registry.antMatchers(HttpMethod.OPTIONS, "/**").denyAll()
//        registry.antMatchers("/**").access("@myAuthorityPermitImpl.hasAuthority(request,authentication)")

        // 自动登录 - cookie储存方式
        .and().rememberMe();
        // 其余所有请求都需要认证
        registry.anyRequest().authenticated()
        // 防止iframe 造成跨域
        .and().headers().frameOptions().disable();
        // 退出路径配置 和成功之后的处理器
        http.logout()
                .logoutUrl("/auth/logout")
                    .logoutSuccessHandler(new MyLogoutSuccessHandler());

        http.addFilterBefore(myAnonymousAuthenticationFilter, AnonymousAuthenticationFilter.class);


    }
}
